package com.sunye.utils;


import com.github.tobato.fastdfs.domain.MataData;
import com.github.tobato.fastdfs.domain.StorageNode;
import com.github.tobato.fastdfs.domain.StorePath;
import com.github.tobato.fastdfs.domain.ThumbImageConfig;
import com.github.tobato.fastdfs.exception.FdfsUnsupportImageTypeException;
import com.github.tobato.fastdfs.exception.FdfsUnsupportStorePathException;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.sunye.upload.config.FastDFSConfig;
import com.sunye.upload.config.OwnThumbImageConfig;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * describe：
 * Created with IDEA
 *
 * @author ryan
 * Date:2021/11/10
 * Time:上午10:37
 */
@Component
public class FastDFSClientWrapper {

    /** 支持的图片类型 */
    private static final String[] SUPPORT_IMAGE_TYPE = { "JPG", "JPEG", "PNG", "GIF", "BMP", "WBMP" };
    private static final List<String> SUPPORT_IMAGE_LIST = Arrays.asList(SUPPORT_IMAGE_TYPE);

    private final Logger logger = LoggerFactory.getLogger(FastDFSClientWrapper.class);

    @Autowired
    private FastFileStorageClient storageClient;

    @Autowired
    private FastDFSConfig appConfig;   // 项目参数配置

    @Autowired
    private VideoProcessing videoProcessing;

    @Resource
    private ThumbImageConfig thumbImageConfig;

    @Autowired
    private DefaultFastFileStorageClientUtil defaultFastFileStorageClientUtil;

    @Autowired
    private OwnThumbImageConfig ownThumbImageConfig;

    /**
     * 上传文件
     *
     * @param file 文件对象
     * @return 文件访问地址
     * @throws IOException
     */
    public Map uploadImageAndCrtThumbImage(MultipartFile file) {
        Map map = new HashMap();
        // 上传并且生成缩略图
        StorePath storePath = null;
        try {
            storePath = this.storageClient.uploadImageAndCrtThumbImage(
                    file.getInputStream(), file.getSize(),FilenameUtils.getExtension(file.getOriginalFilename()), null);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //原图
        String imageUrl = getResAccessUrl(storePath);
        map.put("imageUrl",imageUrl);
        //配置文件中设置高与宽
        String thumbImageUrl = getThumbImageUrl(storePath);
        map.put("thumbImageUrl",thumbImageUrl);
        return map;

    }



    /**
     * 上传文件
     *
     * @param file 文件对象
     * @return 文件访问地址
     * @throws IOException
     */
    public Map uploadOwnImageAndCrtThumbImage(MultipartFile file) {
        Map map = new HashMap();
        // 上传并且生成缩略图
        StorePath storePath = null;
        // 自定义一个高与宽 生成缩率图
        try {
            storePath = defaultFastFileStorageClientUtil.uploadImageAndCrtThumbImage(
                    file.getInputStream(), file.getSize(),FilenameUtils.getExtension(file.getOriginalFilename()), null);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //原图
        String imageUrl = getResAccessUrl(storePath);
        map.put("imageUrl",imageUrl);
        //缩率图1
        String thumbImageUrl = getThumbImageUrl(storePath);
        map.put("thumbImageUrl",thumbImageUrl);
        //缩率图2
        String thumbImageUrlTwo = getThumbImageUrlTwo(storePath);
        map.put("thumbImageUrlTwo",thumbImageUrlTwo);
        return map;

    }

    /**
     * 上传文件(上传视频截图第一帧)
     *
     * @param file 文件对象
     * @return 文件访问地址
     * @throws IOException
     */
    public Map uploadByfastDfs(MultipartFile file) throws IOException {
        Map map = new HashMap();
        try {
            StorePath storePath = null;
            String originalFilename = file.getOriginalFilename();
            //如果是图片压缩
            if(originalFilename.endsWith(".jpg") || originalFilename.endsWith(".png") || originalFilename.endsWith(".bmp") ||originalFilename.endsWith(".webp") || originalFilename.endsWith(".tif") || originalFilename.endsWith(".gif") || originalFilename.endsWith(".apng") ){
                byte[] bytes = compressPicCycle(file.getBytes(), 2000, 0.8);//压缩2M以下
                InputStream inputStream = new ByteArrayInputStream(bytes);
                MultipartFile compressFile = new MockMultipartFile(MediaType.APPLICATION_OCTET_STREAM_VALUE, inputStream);
                storePath = storageClient.uploadFile(compressFile.getInputStream(), compressFile.getSize(), FilenameUtils.getExtension(file.getOriginalFilename()), null);
            }else{
                storePath = storageClient.uploadFile(file.getInputStream(), file.getSize(), FilenameUtils.getExtension(file.getOriginalFilename()), null);
            }
            String resAccessUrl = getResAccessUrl(storePath);
            map.put("path",resAccessUrl);
            //视频缩略图
            StorePath videoImgStorePath = videoProcessing.fileUpload(resAccessUrl);
            if(videoImgStorePath !=null){
                map.put("videoImgPath",getResAccessUrl(videoImgStorePath));
            }else{
                map.put("videoImgPath","");
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return map;
    }

    /**
     * 将一段字符串生成一个文件上传
     *
     * @param content       文件内容
     * @param fileExtension
     * @return
     */
    public String uploadFile(String content, String fileExtension) {
        byte[] buff = content.getBytes(StandardCharsets.UTF_8);
        ByteArrayInputStream stream = new ByteArrayInputStream(buff);
        StorePath storePath = storageClient.uploadFile(stream, buff.length, fileExtension, null);
        return getResAccessUrl(storePath);
    }

    // 封装图片完整URL地址
    private String getResAccessUrl(StorePath storePath) {
        return "http://" + appConfig.getResHost()
                + ":" + appConfig.getFdfsStoragePort() + "/" + storePath.getFullPath();
    }


    private String getThumbImageUrl(StorePath storePath) {
        return "http://" + appConfig.getResHost()
                + ":" + appConfig.getFdfsStoragePort() + "/" +appConfig.getGroup()+ "/" + thumbImageConfig.getThumbImagePath(storePath.getPath());
    }


    private String getThumbImageUrlTwo(StorePath storePath) {
        return "http://" + appConfig.getResHost()
                + ":" + appConfig.getFdfsStoragePort() + "/" +appConfig.getGroup()+ "/" + ownThumbImageConfig.getThumbImagePath(storePath.getPath());
    }

    /**
     * 删除文件
     *
     * @param fileUrl 文件访问地址
     * @return
     */
    public void deleteFile(String fileUrl) {
        if (StringUtils.isEmpty(fileUrl)) {
            return;
        }
        try {
            StorePath storePath = StorePath.praseFromUrl(fileUrl);
            storageClient.deleteFile(appConfig.getGroup(), storePath.getPath());
        } catch (FdfsUnsupportStorePathException e) {
            logger.warn(e.getMessage());
        }
    }


    /**
     * 是否是支持的图片文件
     *
     * @param fileExtName
     * @return
     */
    private boolean isSupportImage(String fileExtName) {
        return SUPPORT_IMAGE_LIST.contains(fileExtName.toUpperCase());
    }

    /**
     * @param bytes       原图片字节数组
     * @param desFileSize 指定图片大小,单位 kb
     * @param accuracy    精度,递归压缩的比率,建议小于0.9
     * @return
     */
    public static byte[] compressPicCycle(byte[] bytes, long desFileSize, double accuracy) throws IOException {
        // 获取目标图片
//        File imgFile = new File(desPath);
//        long fileSize = imgFile.length();
        long fileSize = bytes.length;
        System.out.println("=====fileSize======== " + fileSize);
        // 判断图片大小是否小于指定图片大小
        if (fileSize <= desFileSize * 1024) {
            return bytes;
        }
        //计算宽高
        BufferedImage bim = ImageIO.read(new ByteArrayInputStream(bytes));
        int imgWidth = bim.getWidth();
//        System.out.println(imgWidth + "====imgWidth=====");
        int imgHeight = bim.getHeight();
        int desWidth = new BigDecimal(imgWidth).multiply(new BigDecimal(accuracy)).intValue();
//        System.out.println(desWidth + "====desWidth=====");
        int desHeight = new BigDecimal(imgHeight).multiply(new BigDecimal(accuracy)).intValue();
        ByteArrayOutputStream baos = new ByteArrayOutputStream(); //字节输出流（写入到内存）
        Thumbnails.of(new ByteArrayInputStream(bytes)).size(desWidth, desHeight).outputQuality(accuracy).toOutputStream(baos);
        //如果不满足要求,递归直至满足要求
        return compressPicCycle(baos.toByteArray(), desFileSize, accuracy);
    }


}
